<?php  
/** 
 * CodeIgniter 
 * 
 * An open source application development framework for PHP 5.2.4 or newer 
 * 
 * NOTICE OF LICENSE 
 * 
 * Licensed under the Open Software License version 3.0 
 * 
 * This source file is subject to the Open Software License (OSL 3.0) that is 
 * bundled with this package in the files license.txt / license.rst.  It is 
 * also available through the world wide web at this URL: 
 * http://opensource.org/licenses/OSL-3.0 
 * If you did not receive a copy of the license and are unable to obtain it 
 * through the world wide web, please send an email to 
 * licensing@ellislab.com so we can send you a copy immediately. 
 * 
 * @package     CodeIgniter 
 * @author      EllisLab Dev Team 
 * @copyright   Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) 
 * @license     http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) 
 * @link        http://codeigniter.com 
 * @since       Version 3.0 
 * @filesource 
 */  
defined('BASEPATH') OR exit('No direct script access allowed');  
  
/** 
 * CodeIgniter Redis Caching Class 
 * 
 * @package    CodeIgniter 
 * @subpackage Libraries 
 * @category   Core 
 * @author     Anton Lindqvist <anton@qvister.se> 
 * @link 
 */  
class CI_Cache_redis extends CI_Driver  
{  
    /** 
     * Default config 
     * 
     * @static 
     * @var array 
     */  
    protected static $_default_config = array(  
        /* 
        'socket_type' => 'tcp', 
        'host' => '127.0.0.1', 
        'password' => NULL, 
        'port' => 6379, 
        'timeout' => 0 
        */  
    );  
  
    /** 
     * Redis connection 
     * 
     * @var Redis 
     */  
    protected $_redis;  
          
        // ------------------------------------------------------------------------  
  
    /** 
     * Get cache 
     * 
     * @param   string  like *$key* 
     * @return  array(hash) 
     */  
    public function keys($key)  
    {  
        return $this->_redis->keys($key);  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Get cache 
     * 
     * @param   string  Cache ID 
     * @return  mixed 
     */  
    public function get($key)  
    {  
        return $this->_redis->get($key);  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * mGet cache 
     * 
     * @param   array   Cache ID Array 
     * @return  mixed 
     */  
    public function mget($keys)  
    {  
        return $this->_redis->mget($keys);  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Save cache 
     * 
     * @param   string  $id Cache ID 
     * @param   mixed   $data   Data to save 
     * @param   int $ttl    Time to live in seconds 
     * @param   bool    $raw    Whether to store the raw value (unused) 
     * @return  bool    TRUE on success, FALSE on failure 
     */  
    public function save($id, $data, $ttl = 60, $raw = FALSE)  
    {  
        return ($ttl)  
            ? $this->_redis->setex($id, $ttl, $data)  
            : $this->_redis->set($id, $data);  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Delete from cache 
     * 
     * @param   string  Cache key 
     * @return  bool 
     */  
    public function delete($key)  
    {  
        return ($this->_redis->delete($key) === 1);  
    }  
  
    /** 
     * hIncrBy a raw value 
     * 
     * @param   string  $id Cache ID 
     * @param   string  $field  Cache ID 
     * @param   int $offset Step/value to add 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function hincrby($key, $field, $value = 1)  
    {  
        return $this->_redis->hIncrBy($key, $field, $value);  
    }  
  
    /** 
     * hIncrByFloat a raw value 
     * 
     * @param   string  $id Cache ID 
     * @param   string  $field  Cache ID 
     * @param   int $offset Step/value to add 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function hincrbyfloat($key, $field, $value = 1)  
    {  
        return $this->_redis->hIncrByFloat($key, $field, $value);  
    }  
  
    /** 
     * lpush a raw value 
     * 
     * @param   string  $key    Cache ID 
     * @param   string  $value  value 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function lpush($key, $value)  
    {  
        return $this->_redis->lPush($key, $value);  
    }  
  
     /** 
     * rpush a raw value 
     * 
     * @param   string  $key    Cache ID 
     * @param   string  $value  value 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function rpush($key, $value)  
    {  
        return $this->_redis->rPush($key, $value);  
    }  
    /** 
     * rpop a raw value 
     * 
     * @param   string  $key    Cache ID 
     * @param   string  $value  value 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function rpop($key)  
    {  
        return $this->_redis->rPop($key);  
    }  
  
     /** 
     * brpop a raw value 
     * 
     * @param   string  $key    Cache ID 
     * @param   string  $ontime 阻塞等待时间 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function brpop($key,$ontime=0)  
    {  
        return $this->_redis->brPop($key,$ontime);  
    }  
      
    /** 
     * lLen a raw value 
     * 
     * @param   string  $key    Cache ID 
     * @return  mixed   Value on success or FALSE on failure 
     */  
    public function llen($key)  
    {  
        return $this->_redis->lLen($key);  
    }  
  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Increment a raw value 
     * 
     * @param   string  $id Cache ID 
     * @param   int $offset Step/value to add 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function increment($id, $offset = 1)  
    {  
        return $this->_redis->exists($id)  
            ? $this->_redis->incr($id, $offset)  
            : FALSE;  
    }  
      
    // ------------------------------------------------------------------------  
  
  
    /** 
     * incrby a raw value 
     * 
     * @param   string  $key Cache ID 
     * @param   int $offset Step/value to add 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function incrby($key, $value = 1)  
    {  
        return  $this->_redis->incrby($key, $value);  
    }  
  
    /** 
     * set a value expire time 
     * 
     * @param   string  $key Cache ID 
     * @param   int $seconds expire seconds 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function expire($key, $seconds)  
    {  
        return $this->_redis->expire($key, $seconds);  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Increment a raw value 
     * 
     * @param   string  $id Cache ID 
     * @param   int $offset Step/value to add 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function hset($alias,$key, $value)  
    {  
        return  $this->_redis->hset($alias,$key, $value);  
    }  
      
      
    // ------------------------------------------------------------------------  
  
    /** 
     * Increment a raw value 
     * 
     * @param   string  $id Cache ID 
     * @param   int $offset Step/value to add 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function hget($alias,$key)  
    {  
        return  $this->_redis->hget($alias,$key);  
    }  
      
      
    // ------------------------------------------------------------------------  
  
    /** 
     * Increment a raw value 
     * 
     * @param   string  $id Cache ID 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function hkeys($alias)  
    {  
        return  $this->_redis->hkeys($alias);  
    }  
  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Increment a raw value 
     * 
     * @param   string  $id Cache ID 
     * @param   int $offset Step/value to add 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function hgetall($alias)  
    {  
        return  $this->_redis->hgetall($alias);  
    }  
      
  
      
    /** 
     * Increment a raw value 
     * 
     * @param   string  $id Cache ID 
     * @param   int $offset Step/value to add 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function hmget($alias,$key)  
    {  
        return  $this->_redis->hmget($alias,$key);  
    }  
  
    /** 
     * del a key value 
     * 
     * @param   string  $id Cache ID 
     * @param   int $offset Step/value to add 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function hdel($alias,$key)  
    {  
        return  $this->_redis->hdel($alias,$key);  
    }  
  
    /** 
     * del a key value 
     * 
     * @param   string  $id Cache ID 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function hvals($alias)  
    {  
        return  $this->_redis->hvals($alias);  
    }  
      
      
    /** 
     * Increment a raw value 
     * 
     * @param   string  $id Cache ID 
     * @param   int $offset Step/value to add 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function hmset($alias,$array)  
    {  
        return  $this->_redis->hmset($alias,$array);  
    }  
      
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Decrement a raw value 
     * 
     * @param   string  $id Cache ID 
     * @param   int $offset Step/value to reduce by 
     * @return  mixed   New value on success or FALSE on failure 
     */  
    public function decrement($id, $offset = 1)  
    {  
        return $this->_redis->exists($id)  
            ? $this->_redis->decr($id, $offset)  
            : FALSE;  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Clean cache 
     * 
     * @return  bool 
     * @see     Redis::flushDB() 
     */  
    public function clean()  
    {  
        return $this->_redis->flushDB();  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Get cache driver info 
     * 
     * @param   string  Not supported in Redis. 
     *          Only included in order to offer a 
     *          consistent cache API. 
     * @return  array 
     * @see     Redis::info() 
     */  
    public function cache_info($type = NULL)  
    {  
        return $this->_redis->info();  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Get cache metadata 
     * 
     * @param   string  Cache key 
     * @return  array 
     */  
    public function get_metadata($key)  
    {  
        $value = $this->get($key);  
  
        if ($value)  
        {  
            return array(  
                'expire' => time() + $this->_redis->ttl($key),  
                'data' => $value  
            );  
        }  
  
        return FALSE;  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Check if Redis driver is supported 
     * 
     * @return  bool 
     */  
    public function is_supported()  
    {  
        if (extension_loaded('redis'))  
        {  
            return $this->_setup_redis();  
        }  
        else  
        {  
            log_message('debug', 'The Redis extension must be loaded to use Redis cache.');  
            return FALSE;  
        }  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
     * Setup Redis config and connection 
     * 
     * Loads Redis config file if present. Will halt execution 
     * if a Redis connection can't be established. 
     * 
     * @return  bool 
     * @see     Redis::connect() 
     */  
    protected function _setup_redis()  
    {  
        $config = array();  
        $CI =& get_instance();  
  
        if ($CI->config->load('redis', TRUE, TRUE))  
        {  
            $config += $CI->config->item('redis');  
        }  
          
        $config = array_merge(self::$_default_config, $config);  
  
        $config = !empty($config['redis'])?$config['redis']:$config;  
        $this->_redis = new Redis();  
  
        try  
        {  
            if ($config['socket_type'] === 'unix')  
            {  
                $success = $this->_redis->connect($config['socket']);  
            }  
            else // tcp socket  
            {  
                $success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);  
            }  
  
            if ( ! $success)  
            {  
                log_message('debug', 'Cache: Redis connection refused. Check the config.');  
                return FALSE;  
            }  
        }  
        catch (RedisException $e)  
        {  
            log_message('debug', 'Cache: Redis connection refused ('.$e->getMessage().')');  
            return FALSE;  
        }  
  
        if (isset($config['password']))  
        {  
            $this->_redis->auth($config['password']);  
        }  
  
        return TRUE;  
    }  
  
    // ------------------------------------------------------------------------  
  
    /** 
 
     * Class destructor 
     * 
     * Closes the connection to Redis if present. 
     * 
     * @return  void 
     */  
    public function __destruct()  
    {  
        if ($this->_redis)  
        {  
            $this->_redis->close();  
        }  
    }  
  
}  
  
/* End of file Cache_redis.php */  
/* Location: ./system/libraries/Cache/drivers/Cache_redis.php */  